// 泛型
// 当你需要函数接受不同类型的参数时，又要保护参数类型(不用any)

// 使用泛型创建一个函数
function id<Type>(value: Type): Type {
    return value
}

// 各种类型调用函数
console.log(id<number>(1))
console.log(id<string>('zy'))
console.log(id<boolean>(false))

function test<Type>(value: Type): string {
    if(value){
        return '真的'
    }
    return '假的'
}

// 简化泛型函数调用
let fun = test('abc')

// 泛型约束
/**
 * 因为可以接收各种类型的参数，
 * 导致有些属性访问不到，
 * 比如不是所有类型都有.length属性
 */
// function test2<Type> (value: Type): Type {
//     return value.length      // 报错，Type类型上没有.length属性
// }

// 1.缩小范围
function test2<Type> (value: Type[]): Type[] {
    console.log(value.length)   // 可以访问到参数的length属性
    return value
}

// 2.extends添加约束条件
interface ILength {
    length: number
}
function test3<Type extends ILength> (value: Type): Type {  // Type extends ILength意为Type必须满足含有接口ILength中的属性
    console.log(value.length)   // 可以访问到参数的length属性
    return value
}
test3([1,2,3])  // 数组含有length属性，不报错 √
// test3(123)  // 基本类型number不含有length属性，报错 ×
test3('zhangyang')  // 基本类型string含有length属性，不报错 √